using FSM.IDal; 
using FSM.IBll; 
using FSM.Model; 
using SqlSugar; 
using System; 
using System.Collections.Generic; 
using System.Text;
using System.Linq;

namespace FSM.Bll 
{ 
    public class SysMenuBll: ISysMenuBll 
    { 
        #region 模块 
        private readonly ISysMenuDal dal;
        private readonly IRelUserRoleBll userRoleBll;
        private readonly IRelMenuActionDal relMenuActionDal;
        public SysMenuBll(ISysMenuDal dal, IRelUserRoleBll userRoleBll, IRelMenuActionDal relMenuActionDal)
        {
            this.dal = dal;
            this.userRoleBll = userRoleBll;
            this.relMenuActionDal = relMenuActionDal;
        }
        #endregion 
 
        #region 查询 
 
        /// <summary> 
        /// 根据键值查询单个信息 
        /// </summary> 
        /// <param name="menu_no">键值</param> 
        /// <returns></returns> 
        public sys_menu Get(string menu_no) 
        { 
            return dal.GetById(menu_no); 
        }

        /// <summary> 
        /// 查询批量信息 
        /// </summary>
        /// <param name="menu_name">菜单名称</param>
        /// <param name="menu_pno">上级菜单代码</param>
        /// <param name="page">页码</param> 
        /// <param name="page_size">每页显示的条数</param> 
        /// <returns></returns> 
        public Tuple<List<sys_menu>, int> List(string menu_name, string menu_pno, int page, int page_size)
        {
            ISugarQueryable<sys_menu> queryable = dal.CreateQueryable();
            queryable.WhereIF(!string.IsNullOrWhiteSpace(menu_name), p => p.menu_name.Contains(menu_name));
            queryable.WhereIF(!string.IsNullOrWhiteSpace(menu_pno), p => p.menu_pno == menu_pno);
            queryable.OrderBy("menu_orderby");
            PageModel pm = new PageModel
            {
                PageIndex = page,
                PageSize = page_size
            };
            Tuple<List<sys_menu>, int> result = dal.GetPageListAndTotal(queryable, pm);
            return result;
        }

        /// <summary>
        /// 获得菜单树信息
        /// </summary>
        /// <param name="menu_pno">上级菜单</param>
        /// <returns></returns>
        public List<sys_menu> Tree(string menu_pno)
        {
            List<sys_menu> menuList = dal.GetList().OrderBy(p=>p.menu_orderby).ToList();
            Dictionary<string, int> dicMenus = new Dictionary<string, int>();
            for(int i = 0; i < menuList.Count; i++)
            {
                dicMenus.Add(menuList[i].menu_no, i);
            }

            List<sys_menu> treeMenus = new List<sys_menu>();
            for (int i = 0; i < menuList.Count; i++)
            {
                sys_menu menu = menuList[i];
                if (menu.menu_pno == menu_pno)
                {
                    treeMenus.Add(menu);
                }
                else
                {
                    if (!string.IsNullOrEmpty(menu.menu_pno) && dicMenus.ContainsKey(menu.menu_pno) && menuList[dicMenus[menu.menu_pno]] != null)
                    {
                        menuList[dicMenus[menu.menu_pno]].children.Add(menu);
                    }
                }
            }

            return treeMenus;
        }

        /// <summary>
        /// 获得菜单树信息包含动作信息)
        /// </summary>
        /// <param name="menu_pno">上级菜单</param>
        /// <returns></returns>
        public List<sys_menu> TreeContainActions(string menu_pno)
        {
            List<sys_menu> menuList = dal.GetList();
            Dictionary<string, int> dicMenus = new Dictionary<string, int>();
            for (int i = 0; i < menuList.Count; i++)
            {
                dicMenus.Add(menuList[i].menu_no, i);
            }

            List<sys_menu> treeMenus = new List<sys_menu>();
            for (int i = 0; i < menuList.Count; i++)
            {
                sys_menu menu = menuList[i];
                if (menu.menu_pno == menu_pno)
                {
                    treeMenus.Add(menu);
                }
                else
                {
                    if (!string.IsNullOrEmpty(menu.menu_pno) && dicMenus.ContainsKey(menu.menu_pno) && menuList[dicMenus[menu.menu_pno]] != null)
                    {
                        menuList[dicMenus[menu.menu_pno]].children.Add(menu);
                    }
                }
            }

            foreach (sys_menu menu in menuList)
            {
                if (menu.children != null && menu.children.Count == 0)
                {
                    //如果没有子菜单，则查询菜单对应的动作信息
                    List<sys_action> menuActions = relMenuActionDal.ListActionsByMenuNo(menu.menu_no);
                    if (menuActions.Count > 0)
                    {
                        menu.children = menuActions.Select(p => new sys_menu()
                        {
                            menu_no = $"{menu.menu_no}|{p.act_no}",
                            menu_name = p.act_name
                        }).ToList();
                    }
                }
            }

            return treeMenus;
        }

        /// <summary>
        /// 获得最新的菜单ID
        /// </summary>
        /// <param name="p_no">上级菜单编号</param>
        /// <returns></returns>
        public string GetNewID(string p_no)
        {
            return dal.GetNewID(p_no);
        }

        #endregion

        #region 提交 

        /// <summary> 
        /// 添加 
        /// </summary> 
        /// <param name="model">实体</param> 
        /// <returns></returns> 
        public bool Insert(sys_menu model) 
        {
            model.menu_no = GetNewID(model.menu_pno);
            model.create_date = DateTime.Now;
            return dal.Insert(model); 
        } 
 
        /// <summary> 
        /// 更新 
        /// </summary> 
        /// <param name="model">实体</param> 
        /// <returns></returns> 
        public bool Update(sys_menu model) 
        {
            dal.BeginTran();
            try
            {
                int result= dal.UpdateExcludeColumns(model, "creater", "create_date");
                if (result == 0) throw new Exception("当前要更新的记录不存在，请刷新后再试");
                if (result > 1) throw new Exception("更新数据异常，请确认数据正确");
                dal.CommitTran();
                return true;
            }
            catch (Exception)
            {
                dal.RollbackTran();
                throw;
            }
        } 
 
        /// <summary> 
        ///  删除 
        /// </summary> 
        /// <param name="menu_no">键值</param> 
        /// <returns></returns> 
        public bool Delete(string menu_no) 
        {
            dal.BeginTran();
            try
            {
                string[] menuNoArr = menu_no.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string menuNo in menuNoArr)
                {
                    DeleteAndSub(menuNo);
                }
                dal.CommitTran();
                return true;
            }
            catch (Exception)
            {
                dal.RollbackTran();
                throw;
            }
        }

        #endregion

        #region 关联方法

        /// <summary>
        /// 通过用户编号获得菜单信息
        /// </summary>
        /// <param name="user_no">用户编号</param>
        /// <returns></returns>
        public List<sys_menu> ListMenusByUser(string user_no)
        {
            //判断用户是否是超级管理员组的，如果是超级管理员组的，则抓取所有菜单信息
            bool isAdmin = userRoleBll.IsAdministrators(user_no);
            if (isAdmin)
            {
                return dal.GetList().OrderBy(p => p.menu_orderby).ToList();
            }
            else
            {
                return dal.ListByUser(user_no).OrderBy(p => p.menu_orderby).ToList();
            }
        }

        /// <summary>
        /// 通过用户编号获得菜单树
        /// </summary>
        /// <param name="user_no">用户编号</param>
        /// <returns></returns>
        public List<sys_menu> TreeByUser(string user_no)
        {
            List<sys_menu> menus = ListMenusByUser(user_no);
            int len = menus.Count;
            Dictionary<string, int> dic = new Dictionary<string, int>();
            for (int i = 0; i < len; i++)
            {
                dic.Add(menus[i].menu_no, i);
            }

            List<sys_menu> tree = new List<sys_menu>();
            foreach (var menu in menus)
            {
                if (menu.menu_pno == "-")
                {
                    tree.Add(menu);
                    continue;
                }

                if (menu.menu_pno != null && dic.ContainsKey(menu.menu_pno) && menus[dic[menu.menu_pno]] != null)
                {
                    menus[dic[menu.menu_pno]].children.Add(menu);
                }
            }
            return tree;
        }

        #endregion

        #region 扩展方法

        /// <summary>
        /// 删除指定节点及其子节点
        /// </summary>
        /// <param name="menu_no">菜单编号</param>
        /// <returns></returns>
        private void DeleteAndSub(string menu_no)
        {
            if (!dal.Delete(menu_no))
            {
                throw new Exception($"删除菜单【{menu_no}】失败");
            }
            List<sys_menu> subList = dal.GetList(p => p.menu_pno == menu_no);
            foreach(sys_menu menu in subList)
            {
                DeleteAndSub(menu.menu_no);
            }
        }

        #endregion
    }
} 
